<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h3 data-lake-id="MwEBd" id="MwEBd"><span data-lake-id="ud369ffb2" id="ud369ffb2">问题发现</span></h3>
  <p data-lake-id="uf7869812" id="uf7869812"><br></p>
  <p data-lake-id="u14ed5f65" id="u14ed5f65"><span data-lake-id="uddd28676" id="uddd28676">某次双十一之前，线上突然出现大量报警。服务的调用方很多人也反馈请求超时的情况很多：</span></p>
  <p data-lake-id="u7aaa107c" id="u7aaa107c"><span data-lake-id="u49e3ab63" id="u49e3ab63">​</span><br></p>
  <p data-lake-id="uae0c09e9" id="uae0c09e9"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1680088560318-03e8f4a4-e243-4be8-96ea-98939a57b8e4.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u0daac02b" id="u0daac02b"><br></p>
  <p data-lake-id="ua63ca423" id="ua63ca423"><span data-lake-id="ua8a1f3a9" id="ua8a1f3a9">后来发现同时线上存在GC耗时特别长，GC也特别频繁的情况</span></p>
  <p data-lake-id="udab22e30" id="udab22e30"><br></p>
  <p data-lake-id="ue2ff47c6" id="ue2ff47c6"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1680088609017-b729a77d-63fc-4118-85f6-267c58902bbb.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_51%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <h3 data-lake-id="BNEcL" id="BNEcL"><span data-lake-id="u9a06b2bc" id="u9a06b2bc">问题定位</span></h3>
  <p data-lake-id="ubbaf5a66" id="ubbaf5a66"><br></p>
  <p data-lake-id="ud0e737d2" id="ud0e737d2"><span data-lake-id="u4465e98a" id="u4465e98a">出现了这个现象之后，我们第一时间取拉了一下线上的堆DUMP。然后用我们的分析工具进行内存泄漏分析。</span></p>
  <p data-lake-id="u7f76bb39" id="u7f76bb39"><span data-lake-id="u8274d982" id="u8274d982">​</span><br></p>
  <blockquote data-lake-id="u4914693c" id="u4914693c">
   <p data-lake-id="u080134c5" id="u080134c5"><span data-lake-id="u26e7e720" id="u26e7e720">如果没有工具，可以用jmap和jhat分析。注意在GC前拉dump</span></p>
  </blockquote>
  <p data-lake-id="u86084c68" id="u86084c68"><span data-lake-id="uca1f5f5b" id="uca1f5f5b">​</span><br></p>
  <p data-lake-id="u0ab3f47c" id="u0ab3f47c"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1680088780184-701990e4-bdd8-4258-a992-afb5ce987dee.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_57%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="udb4c6219" id="udb4c6219"><br></p>
  <p data-lake-id="u2efd7299" id="u2efd7299"><span data-lake-id="u47bcc757" id="u47bcc757">可以看到，我们的一个LinkedList占用了73%的内存，很容易识别出来是发生了内存泄漏的问题。</span></p>
  <p data-lake-id="u9ab299e4" id="u9ab299e4"><span data-lake-id="u53852b0c" id="u53852b0c">​</span><br></p>
  <p data-lake-id="u18125bf2" id="u18125bf2" style="text-align: left"><span data-lake-id="uebcfaad8" id="uebcfaad8">该代码于问题发生前几日上线，目的是实现批量支付透支多笔算法，根据代码定位是这个算法存在问题，为了止血，第一时间通过配置中心将算法全部切回单笔算法，保证额度中心系统稳定后，继续进行分析。</span></p>
  <p data-lake-id="u0fb7a1d7" id="u0fb7a1d7" style="text-align: left"><span data-lake-id="u9fb42988" id="u9fb42988">​</span><br></p>
  <p data-lake-id="u2c12df7c" id="u2c12df7c" style="text-align: left"><span data-lake-id="u6142071b" id="u6142071b">根据崩溃线程可以看到程序在不断递归，递归的过程中内存不足了。</span></p>
  <p data-lake-id="ud4b334af" id="ud4b334af" style="text-align: left"><span data-lake-id="u68ae7a6a" id="u68ae7a6a">​</span><br></p>
  <p data-lake-id="u998f5854" id="u998f5854" style="text-align: left"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1680088974085-5e23591c-835e-44fa-bc75-13ba2991fb31.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_49%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u1e5bc6e0" id="u1e5bc6e0" style="text-align: left"><br></p>
  <p data-lake-id="u243ce70e" id="u243ce70e" style="text-align: left"><span data-lake-id="u258337f2" id="u258337f2">然后顺腾摸瓜，找到了具体的case,</span></p>
  <p data-lake-id="ud780bed6" id="ud780bed6" style="text-align: left"><span data-lake-id="u46a075cc" id="u46a075cc">​</span><br></p>
  <p data-lake-id="ub03b1c51" id="ub03b1c51" style="text-align: left"><span data-lake-id="udde1f8f8" id="udde1f8f8">然后定位到出现问题的代码，该算法输入一组订单input，以及该批订单最高可用额度maxQuota，返回最接近maxQuota的一组订单，实现用户可用额度应用尽用。</span></p>
  <p data-lake-id="u7ccdaa2c" id="u7ccdaa2c" style="text-align: left"><span data-lake-id="uce765722" id="uce765722">​</span><br></p>
  <p data-lake-id="u09917dfe" id="u09917dfe" style="text-align: left"><span data-lake-id="uf78e33c6" id="uf78e33c6">本质是一个nums与goal的问题，开发这个代码的同学认为这个问题在leetcode上是一道真题，</span><a href="https://leetcode.cn/problems/closest-subsequence-sum/solution/by-mountain-ocean-1s0v/" target="_blank" data-lake-id="ud9a03e6d" id="ud9a03e6d"><span data-lake-id="ua15d7792" id="ua15d7792">https://leetcode.cn/problems/closest-subsequence-sum/solution/by-mountain-ocean-1s0v/</span></a><span data-lake-id="u7b3e5647" id="u7b3e5647">，我们解决这个问题的思路是分治加回溯，预计时间复杂度是o(n*(2^(2/n)))，</span></p>
  <p data-lake-id="u6c860a7d" id="u6c860a7d" style="text-align: left"><span data-lake-id="ua00b5b82" id="ua00b5b82">​</span><br></p>
  <p data-lake-id="ub3d4cd8d" id="ub3d4cd8d" style="text-align: left"><span data-lake-id="uc92d1bb4" id="uc92d1bb4">但是跟leetcode的需求不同的在于需求记录最接近目标值的一组订单，因为最后要返回的是订单序列，这也是为什么空间复杂度打爆的原因。</span></p>
  <p data-lake-id="u1175fcb0" id="u1175fcb0" style="text-align: left"><span data-lake-id="u56685d0f" id="u56685d0f">​</span><br></p>
  <p data-lake-id="uef09eca3" id="uef09eca3" style="text-align: left"><span data-lake-id="uabf8b1e1" id="uabf8b1e1">出问题的代码就不贴了，主要是开发者只考虑了时间复杂度，没考虑空间复杂度，导致OOM</span></p>
  <h3 data-lake-id="c3gpX" id="c3gpX"><br></h3>
  <h3 data-lake-id="OzzZ5" id="OzzZ5"><span data-lake-id="u8441c6aa" id="u8441c6aa">问题解决</span></h3>
  <p data-lake-id="u6addadc8" id="u6addadc8"><br></p>
  <p data-lake-id="u11d8d4a4" id="u11d8d4a4"><span data-lake-id="ue667cde9" id="ue667cde9">定位到问题之后，就做了一把简单的优化，把"算法"干掉了，通过简单的方式其实就能实现。</span></p>
  <p data-lake-id="u27c9cefb" id="u27c9cefb"><span data-lake-id="u75b99527" id="u75b99527">​</span><br></p>
  <p data-lake-id="u89adf5d7" id="u89adf5d7"><strong><span data-lake-id="u1e0512de" id="u1e0512de">这个问题告诫我们，不要炫技！</span></strong></p>
  <p data-lake-id="u81e6d050" id="u81e6d050"><br></p>
  <p data-lake-id="uab2ebed1" id="uab2ebed1"><br></p>
 </body>
</html>